home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
EDITOR
/
VIEW002.ARJ
/
VIEW.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-14
|
25KB
|
1,051 lines
/*
View 0.02 - A simple,small,windowed, text file viewer.
Copyright (c) 1991 James P. Goodwin.
All rights reserved.
Redistribution and use in source and binary forms are per-
mitted provided that the above copyright notice is dupli-
cated in all such forms and that any documentation,
advertising materials, and other materials related to such
distribution and use acknowledge that the software was
developed by James P. Goodwin.
THE SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PAR-
TICULAR PURPOSE.
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <io.h>
#include <share.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <share.h>
#include <conio.h>
#include <limits.h>
#include <direct.h>
#include "view.h"
/*
GLOBAL variable initialization
*/
VIEW *viewstack = NULL; /* pointer to the bottom view on screen */
UCHAR _far *screen; /* pointer to display ram */
#if VIEW_HAS_MEMORY
/* huge 0 pointer to memory */
UCHAR _huge *memory = (char _huge *)0;
#endif
/* characters used in hex/dec conversion routines */
UCHAR hexdigits[] = {"0123456789ABCDEF"};
int view_offset = 0; /* current offset into display memory */
int view_attr = 0; /* current display attribute */
int view_is_mono = FALSE; /* flag indicates mono (TRUE) or color (FALSE) */
int view_cols = 80;
int view_rows = 25;
UCHAR _far *bios_rows = (UCHAR _far *)0x00400084;
UINT _far *bios_cols = (UINT _far *)0x0040004A;
UCHAR *view_line = NULL; /* line input buffer */
#if VIEW_HAS_DIR
UCHAR *view_curdir = NULL; /* current directory when view entered */
UINT view_curdrive = 0;
#endif
/*
Array of attributes for color and monochrome displays
*/
int view_attr_list[2][5] = {
{ /* Color Attributes */
0x1f, /* Active Window */
0x30, /* Inactive Window */
0x4f, /* Error Message */
0x1b, /* Get a String */
0x31 /* Get a String Cursor */
},
{ /* Mono Attributes */
0x0f, /* Active Window */
0x70, /* Inactive Window */
0x0f, /* Error Message */
0x01, /* Get a String */
0x70 /* Get a String Cursor */
}
};
/*
Function: main( int argc, UCHAR *argv[] )
Description:
This function will :
1) close any "extra" file handles we inherited from
whoever ran us to give us more views
2) save the current directory
3) figure out whether we're in color or monochrome and set the
video buffer address in screen
4) check the standard input to see if it's a file and
if so add it to the list of views and open a new standard
input.
5) if we have no command line arguments prompt for file name
6) process all command line arguments as if they were file names
7) go into the view user interface and view files
8) if we exit this way restore current directory
*/
main( int argc, UCHAR *argv[] )
{
int i;
char fname[15];
_harderr(view_errfunc);
/* Close "extra" file handles */
_dos_close(fileno(stderr));
_dos_close(fileno(stdaux));
_dos_close(fileno(stdprn));
_dos_close(fileno(stdout));
/* Assume :) that video mode 7 is monochrome */
if (view_getvidmode() == 7)
{
view_is_mono = TRUE;
screen = (UCHAR _far *)0xB0000000;
}
else
{
view_is_mono = FALSE;
screen = (UCHAR _far *)0xB8000000;
}
view_rows = (*bios_rows)+1;
view_cols = (*bios_cols);
/* Save the current directory */
#if VIEW_HAS_DIR
_dos_getdrive(&view_curdrive);
view_curdir = getcwd(NULL,80);
if (!view_curdir)
view_error(1,"VIEW0001");
#endif
/* If stdin is a file then add it */
if (!isatty(fileno(stdin)))
view_new(NULL,0,0,16,45);
/* If no args prompt for file */
if (argc <= 1 && !viewstack )
{
#if VIEW_HAS_NEWFILE
view_newfile();
#else
view_error(1,"[command |]VIEW [<filename] [filename .. filenameN]");
#endif
}
else /* process args as file names */
{
for (i = 1; i < argc; i ++)
view_new(argv[i],0,0,16,45);
}
/* put it on the screen and play */
/* with it */
view();
#if VIEW_HAS_DIR
if (view_curdir) /* return to saved dir and release memory */
{
_dos_setdrive(view_curdrive,&i);
chdir(view_curdir);
free(view_curdir);
}
#endif
}
/*
Function: void view(void)
Description:
This function puts up the user interface for view and accepts the
users input. It is basically a big switch on what key they hit. The
keys break down into extended and regular, extended keys are always
preceded by a null scan code.
There are a set of offsets row_offset,col_offset etc... these are
set when certain keys are hit and are added to their corresponding
fields. The view_refresh routine enforces all dimensional constraints
so we don't worry about "overflow" or "underflow" in this routine.
If page_offset is set to a non-zero value then the file is read
either forwards or backwards abs(page_offset) times.
The different refresh modes are used to speed up the screen update
when only the top window needs to be updated or only the top window's
contents.
*/
void view(void)
{
int c1; /* first character read */
int c2; /* second character read */
int row_offset; /* change row of window */
int col_offset; /* change col of window */
int height_offset; /* change height of window */
int width_offset; /* change width of window */
int line_offset; /* change coff of window */
int page_offset; /* change page of contents of window */
int refresh_mode; /* see refresh modes in view.h */
VIEW *top; /* temporary ptr to top window */
if (!viewstack) return; /* there aren't any views so return */
if (!view_line) /* allocate the line buffer if NULL */
{
if (!(view_line = malloc(VIEW_MAX_LINE+1)))
view_error(1,"VIEW0002");
}
view_tile(); /* arrange the windows nicely */
top = viewstack;
do
{
view_scroll(top,SCROLL_RESET);
top = top->next;
}
while( top != viewstack );
view_refresh(REFRESH_ALL); /* put them on the screen */
for(;;)
{
refresh_mode = REFRESH_ALL; /* reset change variables */
row_offset = 0;
col_offset = 0;
height_offset= 0;
width_offset = 0;
line_offset = 0;
page_offset = SCROLL_NONE;
c1 = getch(); /* get a keystroke from console */
switch( c1 ) /* select an action based on key */
{
case 0: /* an extended key follows */
c2 = getch(); /* get extended keysroke */
switch(c2)
{
case CURSOR_DOWN:
refresh_mode = REFRESH_CONTENTS;
page_offset = SCROLL_DOWN;
break;
case CURSOR_LEFT:
refresh_mode = REFRESH_CONTENTS;
line_offset = -3;
break;
case CURSOR_RIGHT:
refresh_mode = REFRESH_CONTENTS;
line_offset = 3;
break;
case CURSOR_UP:
refresh_mode = REFRESH_CONTENTS;
page_offset = SCROLL_UP;
break;
case CNTL_CURSOR_LEFT:
refresh_mode = REFRESH_TOP;
col_offset = -3;
break;
case CNTL_CURSOR_RIGHT:
refresh_mode = REFRESH_TOP;
col_offset = 3;
break;
case CNTL_PGUP:
refresh_mode = REFRESH_TOP;
row_offset = -1;
break;
case CNTL_PGDN:
refresh_mode = REFRESH_TOP;
row_offset = 1;
break;
case CNTL_HOME:
view_tile();
height_offset = view_rows;
width_offset = view_cols;
break;
case CNTL_END:
view_tile();
break;
case PGDN:
refresh_mode = REFRESH_CONTENTS;
page_offset = SCROLL_PAGE_DOWN;
break;
case PGUP:
refresh_mode = REFRESH_CONTENTS;
page_offset = SCROLL_PAGE_UP;
break;
case HOME:
refresh_mode = REFRESH_CONTENTS;
page_offset = SCROLL_HOME;
break;
case END:
refresh_mode = REFRESH_CONTENTS;
page_offset = SCROLL_END;
break;
case SHIFT_TAB:
view_refresh(REFRESH_PREV);
page_offset = SCROLL_RESET;
break;
default:
continue;
}
break;
case 'e':
case 'E':
view_refresh(REFRESH_OFF);
if (view_rows < 43)
{
_asm
{
push es
mov ax,40H
mov es,ax
push es:[87H]
or byte ptr es:[87H],1
mov ax,1112H
xor bx,bx
int 10h
pop es:[87H]
pop es
mov ax,1200H
mov bx,0020H
int 10h
}
}
else
{
_asm
{
push es
mov ax,40H
mov es,ax
push es:[87H]
or byte ptr es:[87H],1
mov ax,1111H
xor bx,bx
int 10h
pop es:[87H]
pop es
}
}
view_rows = (*bios_rows)+1;
view_cols = (*bios_cols);
view_tile();
refresh_mode = REFRESH_ALL;
break;
case 'w':
refresh_mode = REFRESH_TOP;
width_offset = -3;
break;
case 'W':
refresh_mode = REFRESH_TOP;
width_offset = 3;
break;
case 'h':
refresh_mode = REFRESH_TOP;
height_offset = -3;
break;
case 'H':
refresh_mode = REFRESH_TOP;
height_offset = 3;
break;
case 'C':
case 'c':
view_new(viewstack->prev->vf->fname,viewstack->prev->row,viewstack->prev->col,viewstack->prev->rows,viewstack->prev->cols);
view_tile();
page_offset = SCROLL_RESET;
break;
#if VIEW_HAS_GOTO
case 'g':
case 'G':
refresh_mode = REFRESH_CONTENTS;
page_offset = SCROLL_RESET;
view_goto_line();
break;
#endif
#if VIEW_HAS_SEARCH
case 'S':
case 's':
refresh_mode = REFRESH_CONTENTS;
page_offset = SCROLL_RESET;
view_search();
break;
#endif
#if VIEW_HAS_NEWFILE
case 'F':
case 'f':
if (!view_newfile()) continue;
view_tile();
page_offset = SCROLL_RESET;
break;
#endif
case 'D':
case 'd':
view_delete();
view_tile();
break;
#if VIEW_HAS_RAW
case 'X':
case 'x':
viewstack->prev->vf->lmode = VIEW_HEX_MODE;
page_offset = SCROLL_RESET;
break;
case 'B':
case 'b':
viewstack->prev->vf->lmode = VIEW_BIN_MODE;
page_offset = SCROLL_RESET;
break;
#endif
case TAB:
view_refresh(REFRESH_NEXT);
page_offset = SCROLL_RESET;
break;
case ESC:
view_quit();
break;
default:
continue;
}
top = viewstack->prev;
top->row += row_offset;
top->col += col_offset;
top->coff += line_offset;
top->rows += height_offset;
top->cols += width_offset;
view_scroll(top,page_offset);
view_refresh(refresh_mode);
}
}
void view_scroll( VIEW *current, int mode )
{
int i;
VIEWFILE *vf;
ULONG *pos;
UCHAR **lines;
if (kbhit())
if (!getch()) getch();
vf = current->vf;
pos = current->pos;
lines = current->lines;
switch( mode )
{
case SCROLL_NONE :
return;
case SCROLL_DOWN :
if (lines[0])
{
view_seek(vf,pos[(VIEW_LINE_VIEW-1)],SEEK_SET);
view_getl_fwd(vf,view_line,VIEW_MAX_LINE);
memmove(pos,pos+1,(VIEW_LINE_VIEW-1)*sizeof(ULONG));
if (lines[0]) free(lines[0]);
memmove(lines,lines+1,(VIEW_LINE_VIEW-1)*sizeof(UCHAR *));
pos[(VIEW_LINE_VIEW-1)] = view_tell(vf);
if (!view_getl_fwd(vf,view_line,VIEW_MAX_LINE))
lines[(VIEW_LINE_VIEW-1)] = view_strdup(view_line);
else
{
lines[(VIEW_LINE_VIEW-1)] = NULL;
pos[(VIEW_LINE_VIEW-1)] = LONG_MAX;
}
}
break;
case SCROLL_UP :
if (pos[0])
{
view_seek(vf,pos[0],SEEK_SET);
memmove(pos+1,pos,(VIEW_LINE_VIEW-1)*sizeof(ULONG));
if (lines[(VIEW_LINE_VIEW-1)]) free(lines[(VIEW_LINE_VIEW-1)]);
memmove(lines+1,lines,(VIEW_LINE_VIEW-1)*sizeof(UCHAR *));
view_getl_bwd(vf,view_line,VIEW_MAX_LINE);
pos[0] = view_tell(vf);
view_getl_fwd(vf,view_line,VIEW_MAX_LINE);
lines[0] = view_strdup(view_line);
}
break;
case SCROLL_PAGE_UP :
for (i = 0; i < (current->rows-2); i++)
view_scroll(current,SCROLL_UP);
break;
case SCROLL_PAGE_DOWN:
for (i = 0; i < (current->rows-2); i++)
view_scroll(current,SCROLL_DOWN);
break;
case SCROLL_HOME :
view_seek(vf,0L,SEEK_SET);
view_scroll(current,SCROLL_RESET);
break;
case SCROLL_END :
view_seek(vf,0L,SEEK_END);
view_scroll(current,SCROLL_RESET);
view_scroll(current,SCROLL_PAGE_UP);
break;
case SCROLL_CLEAR :
for (i = 0; i < VIEW_LINE_VIEW; i ++)
{
pos[i] = LONG_MAX;
if (lines[i])
{
free(lines[i]);
lines[i] = NULL;
}
}
return;
break;
case SCROLL_RESET :
view_scroll(current,SCROLL_CLEAR);
for (i = 0; i < VIEW_LINE_VIEW; i ++ )
{
pos[i] = view_tell(vf);
if (!view_getl_fwd(vf,view_line,VIEW_MAX_LINE))
lines[i] = view_strdup(view_line);
else
break;
}
break;
}
view_seek(vf,pos[0],SEEK_SET);
}
void view_new( UCHAR *fname, int row,int col,int rows,int cols )
{
VIEW *new;
int th;
if (!strcmp(fname,"Standard Input")) return;
new = (VIEW *)malloc(sizeof(VIEW));
if (!new) view_error(1,"VIEW0003");
if (!(new->vf = view_open(fname)))
{
free(new);
return;
}
new->row = row;
new->col = col;
new->rows = rows;
new->cols = cols;
memset(new->pos,'\0',VIEW_LINE_VIEW*sizeof(ULONG));
memset(new->lines,'\0',VIEW_LINE_VIEW*sizeof(UCHAR *));
new->coff = 0;
new->save = NULL;
if (viewstack == NULL)
{
new->next = new;
new->prev = new;
viewstack = new;
}
else
{
new->next = viewstack;
new->prev = viewstack->prev;
viewstack->prev->next = new;
viewstack->prev = new;
}
}
void view_restore( VIEW *trav )
{
view_putsave(trav->save);
trav->save = NULL;
}
void view_save( VIEW *trav )
{
trav->save = view_getsave(trav->row,trav->col,trav->rows,trav->cols);
}
void view_refresh(int refresh_mode)
{
VIEW *trav;
int r;
int blank;
UCHAR _far *oscreen;
if (refresh_mode != REFRESH_CONTENTS && refresh_mode != REFRESH_TOP)
{
oscreen = screen;
screen = malloc(view_rows*(view_cols*2));
if (!screen)
{
screen = oscreen;
}
else
{
memmove(screen,oscreen,view_rows*(view_cols*2));
}
}
if (refresh_mode != REFRESH_CONTENTS)
{
trav = viewstack->prev;
do
{
if (trav->save)
view_restore(trav);
trav = trav->prev;
if (refresh_mode == REFRESH_CONTENTS || refresh_mode == REFRESH_TOP) break;
}
while(trav != viewstack->prev);
}
if (refresh_mode == REFRESH_NEXT)
{
viewstack = viewstack->next;
refresh_mode = REFRESH_ALL;
}
if (refresh_mode == REFRESH_PREV)
{
viewstack = viewstack->prev;
refresh_mode = REFRESH_ALL;
}
if (refresh_mode != REFRESH_OFF)
{
if (refresh_mode != REFRESH_ALL)
trav = viewstack->prev;
else
trav = viewstack;
do
{
if (trav == viewstack->prev)
view_attr = ACTIVE_WINDOW;
else
view_attr = INACTIVE_WINDOW;
trav->rows = max(trav->rows,3);
trav->rows = min(trav->rows,view_rows);
trav->cols = max(trav->cols,3);
trav->cols = min(trav->cols,view_cols);
trav->col = max(trav->col,0);
trav->col = min(trav->col,view_cols-trav->cols);
trav->row = max(trav->row,0);
trav->row = min(trav->row,view_rows-trav->rows);
trav->coff = max(trav->coff,0);
if (refresh_mode != REFRESH_CONTENTS)
{
view_save(trav);
view_frame(trav->vf->fname,trav->row,trav->col,trav->rows,trav->cols);
}
for (r = 1; r < trav->rows-1; r ++)
{
blank = TRUE;
view_goto(trav->row+r,trav->col+1);
if (trav->lines[r-1] && (strlen(trav->lines[r-1]) > trav->coff))
{
view_puts(trav->lines[r-1]+trav->coff,trav->cols-2);
blank = FALSE;
}
if (blank) view_fill(' ',trav->cols-2);
}
trav = trav->next;
if (refresh_mode != REFRESH_ALL) break;
}
while(trav != viewstack);
}
if (refresh_mode == REFRESH_ALL || refresh_mode == REFRESH_OFF)
{
if (screen != oscreen)
{
memmove(oscreen,screen,view_rows*(view_cols*2));
free(screen);
screen = oscreen;
}
}
}
void view_quit( void )
{
for(;;) view_delete();
}
void view_tile( void )
{
#if VIEW_HAS_TILE
VIEW *trav;
int windows;
int vsize,hsize;
int row,col;
if (!viewstack) return;
windows = 0;
trav = viewstack;
do
{
windows ++;
trav = trav->next;
}
while (trav != viewstack);
hsize = view_cols;
vsize = view_rows;
while ( (view_cols/hsize)*(view_rows/vsize) < windows )
vsize --;
if (vsize < 3)
{
vsize = view_rows;
while ( (view_cols/hsize)*(view_rows/vsize) < windows )
hsize --;
}
if (hsize < 10)
{
hsize = view_cols;
vsize = 24;
while ( (view_cols/hsize)*(view_rows/vsize) < windows )
{
hsize -= 3;
vsize --;
}
}
trav = viewstack;
row = 0;
col = 0;
do
{
trav->row = row;
trav->col = col;
trav->rows = vsize;
trav->cols = hsize;
col += hsize;
if (col+hsize > view_cols)
{
col = 0;
row += vsize;
}
trav = trav->next;
}
while(trav != viewstack);
#endif /* VIEW_HAS_TILE */
}
void view_delete( void )
{
VIEW *hold;
int lets_exit = FALSE;
if (viewstack->prev == viewstack)
lets_exit = TRUE;
hold = viewstack->prev;
viewstack->prev->prev->next = viewstack;
viewstack->prev = viewstack->prev->prev;
view_restore(hold);
view_scroll(hold,SCROLL_CLEAR);
view_close(hold->vf);
free(hold);
if (lets_exit)
{
if (view_line) free(view_line);
#if VIEW_HAS_DIR
if (view_curdir)
{
_dos_setdrive(view_curdrive,&lets_exit);
chdir(view_curdir);
free(view_curdir);
}
#endif
exit(0);
}
}
#if VIEW_HAS_NEWFILE
int view_newfile( void )
{
int c1,c2;
char fname[80];
fname[0] = '\0';
do
{
c1 = view_prompt("New File","Filename:",fname,40);
#if VIEW_HAS_DIR
if (c1 && !strlen(fname))
c1 = view_dir(fname);
#endif
if (c1 && (c2 = (access(fname,0)
#if VIEW_HAS_MEMORY
&& stricmp(fname,VIEW_MEM_NAME)
#endif
)))
{
strcpy(fname,"File Not Found");
}
}
while(c1 && c2);
if (c1)
{
view_new(fname,0,0,16,45);
return(TRUE);
}
else
return(FALSE);
}
#endif /* VIEW_HAS_NEWFILE */
#if VIEW_HAS_SEARCH
int view_search( void )
{
int c1,c2;
char pat[80];
UCHAR *found;
ULONG pos;
int ret;
VIEWFILE *vf;
vf = viewstack->prev->vf;
pat[0] = '\0';
do
{
c1 = view_prompt("Search","Pattern:",pat,40);
if (c1)
{
view_seek(vf,viewstack->prev->pos[0],SEEK_SET);
ret = 0;
found = NULL;
while(!ret && !found)
{
pos = view_tell(vf);
ret = view_getl_fwd(vf,view_line,VIEW_MAX_LINE);
if (!ret) found = strstr(view_line,pat);
}
if (found)
{
view_seek(vf,pos,SEEK_SET);
viewstack->prev->coff = found-view_line;
return(TRUE);
}
else
strcpy(pat,"Pattern Not Found");
}
}
while(c1);
return(FALSE);
}
#endif
#if VIEW_HAS_GOTO
void view_goto_line( void )
{
int c1;
char pat[80];
ULONG pos;
int ret;
VIEWFILE *vf;
UCHAR *goto_pmt[] = {"Offset In File:","Memory Address (SSSSOOOO):","Line Number:"};
int goto_len[] = { 10, 8, 8 };
int goto_base[] = { 10,16,10 };
int goto_type;
pat[0] = '\0';
vf = viewstack->prev->vf;
#if VIEW_HAS_RAW
if (vf->lmode
#if VIEW_HAS_MEMORY
&& vf->fh != VIEW_MEM_HDL
#endif
)
goto_type = 0;
#if VIEW_HAS_MEMORY
else if (vf->lmode && vf->fh == VIEW_MEM_HDL )
goto_type = 1;
#endif
else
#endif /* VIEW_HAS_RAW */
goto_type = 2;
c1 = view_prompt("Goto",goto_pmt[goto_type],pat,goto_len[goto_type]);
if (c1)
{
pos = view_atoul(pat,goto_base[goto_type]);
switch(goto_type)
{
#if VIEW_HAS_RAW
case 0:
view_seek(vf,pos,SEEK_SET);
break;
#endif
#if VIEW_HAS_MEMORY
case 1:
view_seek(vf,(ULONG)(((UCHAR _huge *)pos)-memory),SEEK_SET);
break;
#endif
case 2:
view_seek(vf,0L,SEEK_SET);
ret = 0;
while (!ret && pos)
{
ret = view_getl_fwd(vf,view_line,VIEW_MAX_LINE);
pos --;
}
break;
}
}
}
#endif /* VIEW_HAS_GOTO */
void _far view_errfunc( void )
{
_hardresume(_HARDERR_FAIL);
}
UCHAR *view_strdup( UCHAR *str )
{
str = strdup(str);
if (!str)
view_error(1,"VIEW0010");
return(str);
}